home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Singles Flirt Up Your Life! (German)
/
Singles Flirt Up Your Life.iso
/
data1.cab
/
Script
/
initGame.lua
< prev
next >
Wrap
Text File
|
2004-01-29
|
71KB
|
2,491 lines
-- globals
include("globals")
-- disable print if wstats is not defined mode
if (not isDefined("WSTATS")) then
print("disabling lua print");
print = function() end
end
-- high level convenience scription functions
-- this: global
-- object: StandardGO
-- checks if this item is on a table, if there is a chair on the closest
-- action point and returns the chair game object, otherwise it returns nil
function getChairForItemOnTable(object, character)
local goParent = object.getGOParent();
-- local currentCharacter = object.getGameObjectServer().getCurrentCharacter();
if (goParent) then
if (goParent.hasBehavior("table")) then
-- check if chair is on action point
-- local chairActionPoint = object.getClosestActionPoint(currentCharacter);
local chairActionPoint = object.getActionPoint("chair");
if (chairActionPoint) then
local chair = object.getGameObjectOnActionPoint(chairActionPoint.getName());
if (chair) then
if (chair.hasBehavior("chair")) then
--orientation must be correct
if (chair.hasActionPointOrientation(chairActionPoint)) then
return chair;
else
print("wrong orientation");
end
else
print("this is not a chair");
end
else
print("must sit on something");
end
else
print("the current object has no action point");
end
else
print("the computer must stand on a table");
end
else
print("the computer must not stand on the ground");
end
return nil;
end
function enumCompare(enum1, enum2)
if (tonumber(enum1) == tonumber(enum2)) then
return true;
else
return false;
end
end
-- this: walkStateObject
-- chooses an action and does the action, if one was chosen
function doSomething()
local character = getParent();
print("doSomething " .. character.getCharacterName() .. "--getActivityQueueCount:" .. character.getActivityQueueCount());
if (character.getActivityQueueCount() == 0) then
-- AI
local ai = character.getGameObjectServer().autonomousCharacters();
if (ai) then
if (not urgentOutfitChange(character)) then
print("doSomething chooseCommand");
local chosenObjectCommand = character.chooseCommand();
if (chosenObjectCommand) then
print("doSomething queue chosenObjectCommand");
character.queueCommand(chosenObjectCommand, true);
else
--print("doSomething goAway");
if (character.isSwimming()) then
sendMsg("goAway", character.walkSO);
else
makeConditionPose();
end
end
end
else
print("doSomething ai disabled");
makeConditionPose();
end
end
end
function urgentOutfitChange(character)
if (not character.getGameObjectServer().automaticActions()) then
return false;
end
if not checkShyness(character) then
return false;
end
local kommoden = character.getPrivateObjectsWithBehavior("kommode");
for k = 1, getn(kommoden) do
local kommode = kommoden[k];
if (not kommode.isBroken()) then
local outfit = character.getOutfitDescription(ARCHTYPE);
character.queueCommand(outfit.getName(), "outfit", kommode, tostring(outfit.getID()));
return true;
end
end
return false;
end
-- this: walkStateObject
--function urgentArgueCharacter(activeCharacter)
--
-- local others = activeCharacter.getOtherCharacters();
--
-- for index, passiveCharacter in others do
-- if (checkInjustice(activeCharacter, passiveCharacter) and not passiveCharacter.isBusy()) then
-- activeCharacter.queueCommand("pm_talkArgue", "talk", passiveCharacter, "Argue");
-- return true;
-- end
-- end
--
-- return false;
--end
function checkInjustice(activeCharacter)
local justiceValue = activeCharacter.getCondition(NEED_JUSTICE);
local tolerance = activeCharacter.getJusticeTolerance();
local passiveCharacter = getOtherCharacter(activeCharacter);
if (justiceValue < activeCharacter.getJusticeTolerance()) and (not passiveCharacter.isBusy()) then
activeCharacter.queueCommand("pm_talkArgue", "talk", passiveCharacter, "Argue");
return true;
end
if (justiceValue < lerp(tolerance, 1.0, tonumber(readConfig("Game", "justiceWarningLevel", "0.3")))) then
activeCharacter.setEmoticon(EMOTICON_JUSTICE, EMOTICON_DELAY);
return true;
end
return false;
end
-- this: walkStateObject
function makeConditionPose()
local character = getParent();
if (not character.getGameObjectServer().automaticActions()) then
return
end
if checkShyness(character) then
return
end
-- if (urgentArgueCharacter(character)) then
-- return
-- end
if checkInjustice(character) then
return
end
local now = character.getGameObjectServer().getGameTime();
local nextPoseTime = character.retrieveData("nextPoseTime", 0);
--print("makeConditionPose: now " .. now .. " nextPoseTime " .. nextPoseTime .. " for " .. character.getCharacterName());
if (now < nextPoseTime) then
--print("makeConditionPose: return now < nextPoseTime");
return
end
character.setEmoticon("");
nextPoseTime = now + random(CONDITION_POSE_PAUSE, CONDITION_POSE_PAUSE * 2);
if (random() > CONDITION_POSE_PROB) then
--print("makeConditionPose: return CONDITION_POSE_PROB");
character.storeData("nextPoseTime", nextPoseTime);
return
end
-- interaction poses
local partner = getOtherCharacter(character);
local needs = character.getNeedsSorted();
local worstNeed = needs[1];
--print(" worstNeed:", worstNeed);
--for testing
if (enumCompare(worstNeed, NEED_APARTMENT)) then worstNeed = needs[2]; end;
local worstNeedValue = character.getCondition(worstNeed);
--print(" worstNeedValue:", worstNeedValue);
if (partner) then
local distance = character.getDistanceToGameObject(partner);
-- smell the other character
if (distance < 2.0) then
local partnersHygiene = partner.getCondition(NEED_HYGIENE);
local partnersState = partner.walkSO.getStateMachine().getName();
if ((partnersHygiene < 0.2) or (partnersState == "toiletChar")) then
partner.sendMsg("emoYouSmell", character.walkSO);
character.setEmoticon(EMOTICON_SMELL, EMOTICON_DELAY);
character.storeData("nextPoseTime", nextPoseTime);
return
end
end
-- flirt
if (distance < 4.0) then
if (enumCompare(worstNeed, NEED_LIBIDO) and (worstNeedValue < 0.2)) then
partner.sendMsg("emoFlirt", character.walkSO);
character.setEmoticon(EMOTICON_EROTIC, EMOTICON_DELAY);
character.storeData("nextPoseTime", nextPoseTime);
return
end
end
end
if (worstNeedValue > 0.7) then
-- happy because all needs satisfied
character.setEmoticon(EMOTICON_SMILE, EMOTICON_DELAY);
sendMsg("emoHappy", character.walkSO);
character.storeData("nextPoseTime", nextPoseTime);
return
end
if (worstNeedValue > 0.2) then
-- nothing really critical
return
end
-- no fun
if (enumCompare(worstNeed, NEED_FUN)) then
sendMsg("emoSwing", character.walkSO);
character.setEmoticon(EMOTICON_SAD, EMOTICON_DELAY);
character.storeData("nextPoseTime", nextPoseTime);
-- no comfort
elseif (enumCompare(worstNeed, NEED_COMFORT)) then
sendMsg("emoSwing", character.walkSO);
character.setEmoticon(EMOTICON_SAD, EMOTICON_DELAY);
character.storeData("nextPoseTime", nextPoseTime);
-- bad apartment
elseif (enumCompare(worstNeed, NEED_APARTMENT)) then
sendMsg("emoThink", character.walkSO);
character.setEmoticon(EMOTICON_APARTMENT, EMOTICON_DELAY);
character.storeData("nextPoseTime", nextPoseTime);
-- no hygiene
elseif (enumCompare(worstNeed, NEED_HYGIENE)) then
sendMsg("emoHygiene", character.walkSO);
character.setEmoticon(EMOTICON_SMELL, EMOTICON_DELAY);
character.storeData("nextPoseTime", nextPoseTime);
-- hungry
elseif (enumCompare(worstNeed, NEED_HUNGER)) then
sendMsg("emoHungry", character.walkSO);
character.setEmoticon(EMOTICON_SAD, EMOTICON_DELAY);
character.storeData("nextPoseTime", nextPoseTime);
-- tired
elseif (enumCompare(worstNeed, NEED_TIREDNESS)) then
sendMsg("emoYawn", character.walkSO);
character.setEmoticon(EMOTICON_SLEEPY, EMOTICON_DELAY);
character.storeData("nextPoseTime", nextPoseTime);
end
end
-- returns true if character activeCharacter is ashamed of passiveCharacter
-- in the current state
function isCharacterAshamed(activeCharacter, passiveCharacter)
if (hasOutfit(activeCharacter, UNDERWEAR) or hasOutfit(activeCharacter, TOWEL)) then
local activity = activeCharacter.createActivity("showInUnderwear", passiveCharacter)
return not enumCompare(activity.getActivityResult(), POSSIBLE)
elseif hasOutfit(activeCharacter, NOTHING) then
local activity = activeCharacter.createActivity("showNaked", passiveCharacter)
return not enumCompare(activity.getActivityResult(), POSSIBLE)
end
return false;
end
function checkShyness(character)
if (hasOutfit(character, UNDERWEAR) or hasOutfit(character, TOWEL)) then
local other, result = getDisturbingChar(character, "showInUnderwear")
if (other) then
--character.setEmoticon(EMOTICON_SHY, EMOTICON_DELAY);
other.sendMsg("emoShameChar", character.walkSO);
return true;
end;
elseif hasOutfit(character, NOTHING) then
local other, result = getDisturbingChar(character, "showNaked")
if (other) then
--character.setEmoticon(EMOTICON_SHY, EMOTICON_DELAY);
other.sendMsg("emoShameNackedChar", character.walkSO);
return true;
end;
end;
return false;
--
-- local others = character.getCharactersInRoom();
--
-- for c = 1, getn(others) do
-- local other = others[c];
-- --print("checkShyness other found");
-- if (not activityPossible(character, "showInUnderwear", other)) then
-- --print("checkShyness sendMsg emoShame");
-- character.setEmoticon(EMOTICON_SHY, EMOTICON_DELAY);
-- other.sendMsg("emoShameChar", character.walkSO);
-- return true;
-- end;
-- end;
--
-- return false;
end
-- looks for other character in same room on wich the given activity is not possible
function getDisturbingChar(character, activity)
local others = character.getCharactersInRoom();
for c = 1, getn(others) do
local other = others[c];
local watchedActionPoint = other.getActionPoint("kiss");
local watchingActionPoint = character.getActionPoint("kiss");
-- check line of sigth
local gameObjectServer = character.getGameObjectServer();
--local blockingObject = gameObjectServer.getGameObjectBetween(watchingActionPoint, watchedActionPoint, 1.5, 1.5);
local blockingObject = character.getGameObjectBetween(other, "center", "center", 1.7, 1.7);
if (not blockingObject) then
if (not character) then print("getDisturbingChar character == nil"); end;
local possible, result = activityPossible(character, activity, other);
if (not possible) then
return other, result;
end;
else
print("getDisturbingChar :: Sight from " .. character.getType() .. " blocked by " .. blockingObject.getType());
return nil;
end
end;
return nil;
end
function getActionPointsInSight(fromObject, fromActionPointName, fromHeight, toObject, toActionPointNames, toHeight, ignoredObject)
local result = {};
for p = 1, getn(toActionPointNames) do
local toActionPointName = toActionPointNames[p];
local blockingObject = fromObject.getGameObjectBetween(toObject, fromActionPointName, toActionPointName, fromHeight, toHeight, true);
if ((not blockingObject) or (blockingObject == ignoredObject)) then
print("getActionPointsInSight toActionPointName:" .. toActionPointName .. " OK");
tinsert(result, toActionPointName);
else
print("getActionPointsInSight toActionPointName:" .. toActionPointName .. " blocked by:" .. blockingObject.getType());
end
end
--print("getActionPointsInSight input: " .. tostring(toActionPointNames))
--print("getActionPointsInSight output: " .. tostring(result))
return result;
end
function getOtherCharacter(thisChar)
if (thisChar) then
local others = thisChar.getOtherCharacters();
return others[1];
else
return nil
end
end
-- this: walkStateObject
function actionComplete()
if (this.actionComplete()) then
doSomething();
end
end
-- this: walkStateObject
-- this is called when the caracter is sleeping
-- returns true if sleeping shall be canceled
function testCancelSleeping()
local goOnSleeping = true
local character = getParent()
-- local currentDate = GameDate.createGameDate(character.getGameObjectServer().getGameTime());
local currentDate = character.getGameObjectServer().getGameDate()
local workPrepareTime = character.retrieveData("workPrepareTime", 2);
local getUpTime = character.getWorkBeginTime().getHoursF() - workPrepareTime;
-- print("testCancelSleeping: " .. character.getCharacterName() .. "-------------------------");
-- print("workPrepareTime: " .. workPrepareTime);
-- print("getUpTime: " .. getUpTime);
-- print("character.getCondition(NEED_TIREDNESS): " .. character.getCondition(NEED_TIREDNESS));
-- print("currentDate.isWorkingDay(): " .. tostring(currentDate.isWorkingDay()));
-- print("currentDate.getHoursF(): " .. currentDate.getHoursF());
-- get up if it is time to get up
-- characters must be at least "minGetUpTiredness" rested
local minGetUpTiredness = tonumber(readConfig("Game", "minGetUpTiredness", "0.8"));
if (character.getCondition(NEED_TIREDNESS) > minGetUpTiredness) then
-- check if this is working day
if (currentDate.isWorkingDay()) then
local sleepActivity = character.getCurrentActivity();
if (currentDate.getHoursF() > getUpTime) then
if (sleepActivity) then
-- local sleepStartDate = GameDate.createGameDate(sleepActivity.getStartTime());
local sleepStartDate = character.getGameObjectServer().createGameDate(sleepActivity.getStartTime());
-- print("sleepStartDate.getDays(): " .. sleepStartDate.getDays());
-- print("currentDate.getDays(): " .. currentDate.getDays());
-- print("sleepStartDate.getHoursF(): " .. sleepStartDate.getHoursF());
if ((sleepStartDate.getDays() < currentDate.getDays()) or
(sleepStartDate.getHoursF() < getUpTime)) then
-- time to get up
goOnSleeping = false
end
end
end
end
end
-- -- get up if normal sleep duration in milliseconds passed
-- if (sleepActivity) then
-- local length = getActivityLength(sleepActivity);
-- local currentTime = character.getGameObjectServer().getGameTime();
-- local startTime = sleepActivity.getStartTime();
-- print("length: " .. length);
-- print("currentTime: " .. currentTime);
-- print("startTime: " .. startTime);
-- if (startTime+length < currentTime) then
-- print("sleep duration passed: start:" .. startTime .. " stoptime:" .. startTime+length .. "currentTime:" .. currentTime);
-- goOnSleeping = false;
-- end
-- end
-- get up if not tired anymore and not in the middle of the night
local currentHours = currentDate.getHoursF();
local nightStart = tonumber(readConfig("Display", "nightTime", "22"));
local nightEnd = tonumber(readConfig("Display", "morningTime", "6"));
if (character.getCondition(NEED_TIREDNESS) > 0.99)
and (currentHours > nightEnd)
and (currentHours < nightStart) then
-- not tired anymore
goOnSleeping = false
end
if (character.hasWalkQueued(1)) then
goOnSleeping = false;
end
return (not goOnSleeping);
end
-- looks for the closest free chair by a table
function getNextFreeChairByTable(character, tableObject, checkPartnerChair)
print("getNextFreeChairByTable");
local tables = character.getObjectsWithBehavior("table");
-- go trough tables
for t = 1, getn(tables) do
print(" table " .. t);
local table = tables[t];
local actionPoints = table.getActionPoints();
-- go trough action points of table
--for a, actionPoint in actionPoints do
for a = 1, getn(actionPoints) do
local actionPoint = actionPoints[a];
local actionPointName = actionPoint.getName();
print(" actionPoint " .. actionPointName);
if (strsub(actionPointName,1,5) == "chair") then
local chair = table.getGameObjectOnActionPoint(actionPointName);
if (chair) then
if (chair.hasBehavior("chair")) then
local chairActionPoint = character.getClosestFreeActionPoint(character, chair, {"sit1", "sit2"}, true);
if (chairActionPoint) then
if (chair.hasActionPointOrientation(actionPoint)) then
local partnerChair = getOpposedChair(table, actionPointName);
print("getNextFreeChairByTable: partnerChair: "..tostring(partnerChair).." checkPartnerChair "..tostring(checkPartnerChair));
if (partnerChair or (not checkPartnerChair)) then
if (tableObject) then
local tablePos = tableObject.tableYPosition;
if (not tablePos) then print("WARNING no attribute -tableYPosition- found"); tablePos = 0; end;
local placeOnTable = table.canObjectBeAddedToActionPoint(tableObject, actionPointName, 0, tablePos, tableHeight);
if (placeOnTable) then
print("getNextFreeChairByTable: enough place for tableObject" .. tableObject.getType());
return table, actionPointName, chair;
else
print("getNextFreeChairByTable: no place on table for tableObject" .. tableObject.getType());
end
else
print("getNextFreeChairByTable: no tableObject to check");
return table, actionPointName, chair;
end
else
print("getNextFreeChairByTable partnerChair not found");
end
else
print("getNextFreeChairByTable: free chair has wrong orient to table");
end
else
print(" getNextFreeChairByTable: chair is blocked");
end
else
print("getNextFreeChairByTable: object is not a chair");
end
else
print("getNextFreeChairByTable:nothing on actionPoint " .. actionPointName);
end
else
print("getNextFreeChairByTable:not a chair actionPoint " .. actionPointName);
end
end
end
return nil;
end
function getChildByStoredData(parent, dataName, data)
local children = parent.getGOChildren();
for c = 1, getn(children) do
local child = children[c];
local childData = child.retrieveData(dataName);
if (childData and (childData == data)) then
return child;
end
end
return nil;
end
function getChildrenWithBehavior(parent, behavior)
local result = {};
local children = parent.getGOChildren();
for c = 1, getn(children) do
local child = children[c];
if (child.hasBehavior(behavior)) then
tinsert(result, child);
end
end
return result;
end
-- returns an object's action point wich is opposed to the action point described by actionPointName
function getOpposedActionPoint(object, actionPointName)
local actionPoint = object.getActionPoint(actionPointName);
if (not actionPoint) then
print("getOpposedActionPoint: no actionpoint with name " , actionPointName);
end
local actionPoints = object.getActionPoints();
for a = 1, getn(actionPoints) do
--local point = actionPoints[a];
--local name = currentActionPoint.getName();
if (not(actionPoints[a].getName() == actionPointName)) then
local facing1 = actionPoints[a].getFacingFraction(actionPoint);
local facing2 = actionPoint.getFacingFraction(actionPoints[a]);
local facing = facing1 + facing2;
if (facing > 1.9) then
return actionPoints[a];
end
end
end
print("getOpposedActionPoint: no opposed actionpoint found for " , actionPointName);
return nil;
end
function getOpposedChair(table, actionPointName)
local oppActionPoint = getOpposedActionPoint(table, actionPointName);
if (not oppActionPoint) then
--print("getOpposedChair: no opposed actionpoint found for " , actionPointName);
return nil;
end
local chair = table.getGameObjectOnActionPoint(oppActionPoint.getName());
if (not chair) then
--print("getOpposedChair: nothing on opposed actionpoint " , oppActionPoint.getName());
return nil;
end
if (not chair.hasBehavior("chair")) then
--print("getOpposedChair: not a chair on opposed actionpoint " , oppActionPoint.getName());
return nil;
end
return chair;
end
function getTableForChair(chair)
local tables = chair.getObjectsWithBehavior("table");
-- go trough tables
for t = 1, getn(tables) do
print(" table " .. t);
local table = tables[t];
local actionPoints = table.getActionPoints();
-- go trough action points of table
for a = 1, getn(actionPoints) do
local actionPoint = actionPoints[a];
local actionPointName = actionPoint.getName();
if (strfind(actionPointName, "chair") == 1) then
print(" actionPoint " .. actionPointName);
local go = table.getGameObjectOnActionPoint(actionPointName);
if (go == chair) then
if (chair.hasActionPointOrientation(actionPoint)) then
print("getTableForChair: return actionPointName " .. actionPointName);
return table, actionPointName;
end
end
end
end
end
return nil;
end
---- this: walk state object
--function goAway()
-- local queueCount = getQueueCount();
-- print("queueCount: " .. queueCount);
-- if (queueCount < 1) then
-- sendMsg("goAway", this);
-- else
-- print("dont go away, somthing to do");
-- end
--end
-- this: walk state object
function exitAndGoAway(minDist)
exitStateMachine()
local activityQueueCount = getParent().getActivityQueueCount();
if (activityQueueCount > 0) then
print("something to do! activityQueueCount:" .. activityQueueCount);
else
print("nothing to do -> go away !!!");
if (minDist) then
sendDelayedMsgThis("goAway", 500, tostring(minDist));
else
sendDelayedMsgThis("goAway", 500);
end
end
end
function queueNextClean(character)
--local character = getParent();
local activityQueueCount = character.getActivityQueueCount();
if (activityQueueCount > 1) then
print("queueNextClean something to do! activityQueueCount:" .. activityQueueCount);
return
end
local tiredness = character.getCondition(NEED_TIREDNESS);
if (tiredness < 0.1) then
print("queueNextClean too tired" .. tiredness);
return
end
local nextDirty = getNextDirtyObject(character);
if (nextDirty) then
print("queueNextClean next:" .. nextDirty.getType());
character.queueCommand("pm_clean", "clean", nextDirty, "");
else
print("queueNextClean nothing to clean");
end
end
function getNextDirtyObject(character)
local cleanables = character.getObjectsWithBehavior("cleanable");
local characterRoom = character.getRoomNumber();
for c = 1, getn(cleanables) do
local cleanable = cleanables[c];
if (cleanable.getDirtiness() > 0.01) and (cleanable.getRoomNumber() == characterRoom) then
return cleanable;
end
end
return nil;
end
function getNextTableWithDishes(character)
local tables = character.getObjectsWithBehavior("table");
local dishFound = false;
-- go trough tables
for t = 1, getn(tables) do
print(" table " .. t);
local table = tables[t];
local dishes = getChildrenWithBehavior(table, "dish");
local dish = dishes[1];
if (dish) then
dishFound = true;
--local actionPoint = character.getClosestFreeActionPoint(dish, table, {"front1", "front2"});
local actionPoint = character.getClosestFreeActionPoint(dish, table);
if (actionPoint) then
return table, actionPoint, dishFound;
else
print("no actionPoint");
end
else
print("no dish");
end
-- if (getn(dishes) > 0) then
-- return table;
-- end
end
return nil, nil, dishFound;
end
function getReachableObjectWithBehavior(character, behavior, actionPointNames, checkBroken)
local objects = character.getObjectsWithBehavior(behavior);
for o = 1, getn(objects) do
local object = objects[o];
if ((not checkBroken) or (not object.isBroken())) then
local actionPoint = character.getClosestFreeActionPoint(character, object, actionPointNames, true);
if (actionPoint) then
return object, actionPoint;
end
end
end
return nil;
end
function getNextReadSit(character)
return getReachableObjectWithBehavior(character, "readSeat", {"sit", "sit1", "sit2", "sit3"}, true)
-- local seats = character.getObjectsWithBehavior("readSeat");
-- print("getNextReadSit total seats" .. getn(seats));
-- for s = 1, getn(seats) do
-- local seat = seats[s];
-- print(" getNextReadSit seat no" .. s);
--
-- if (not seat.isBroken()) then
--
-- print("seat " .. s .. " is " .. seats[s].getResourceName());
-- local actionPoint = character.getClosestFreeActionPoint(character, seat, {"sit", "sit1", "sit2", "sit3"}, true);
-- if (actionPoint) then
-- return seat, actionPoint;
-- end
--
-- end
-- end
-- return nil;
end
-- looks for a seat to watch an objects "watch" actionpoint
function getNextWatchSit(character, watchedObject, objectHeight, seatHeigth)
print("getNextWatchSit");
watchedActionPoint = watchedObject.getActionPoint("watch");
if (not watchedActionPoint) then
print("watchedObject has no action point --watch--");
return nil;
end
local bestSeat = nil;
local bestActionPointName = "";
local bestFacing = 1;
local maxFacing = MAX_WATCH_FACING;
local maxDistance = MAX_WATCH_DISTANCE;
local gameObjectServer = watchedObject.getGameObjectServer();
local seats = watchedObject.getObjectsWithBehavior("watchSeat", maxDistance + 1);
for s = 1, getn(seats) do
local seat = seats[s];
print(" seat:" .. s .. " type:" .. seat.getType());
if (not seat.isBroken()) then
local actionPoints = character.getFreeActionPoints(seat, {"sit", "sit1", "sit2", "sit3"});
for a = 1, getn(actionPoints) do
local actionPoint = actionPoints[a];
if (character.canReachActionPoint(actionPoint)) then
local facing1 = actionPoint.getFacingFraction(watchedActionPoint);
local facing2 = watchedActionPoint.getFacingFraction(actionPoint);
local facing = max(facing1, facing2); --facing1 + facing2;
local distance = actionPoint.getDistance(watchedActionPoint)
print("getNextWatchSit distance:"..distance.." facing1:"..facing1.." facing2:"..facing2.." facing:"..facing.." maxFacing:"..maxFacing);
if ((facing < MAX_WATCH_FACING) and (distance < MAX_WATCH_DISTANCE)) then
if (facing < bestFacing) then
-- check line of sigth
-- local blockingObject = character.getGameObjectBetween(actionPoints[a], watchedActionPoint, seatHeigth, objectHeight);
local blockingObject = seat.getGameObjectBetween(watchedObject, actionPoint.getName(), watchedActionPoint.getName(), seatHeigth, objectHeight, true);
if (not blockingObject) then
bestSeat = seat;
bestActionPointName = actionPoint.getName();
bestFacing = facing;
else
print("Sight from action point " .. actionPoint.getName() .. " blocked by " .. blockingObject.getResourceName());
end
end
end
end
end
else
print("seat " .. seat.getType() .. " broken");
end
end
if (bestSeat) then
print("bestActionPoint: " .. bestActionPointName .. " bestFacing" .. bestFacing);
return bestSeat, bestSeat.getActionPoint(bestActionPointName);
else
print("no watching ActionPoint found");
return nil;
end
end
-- frees the hands of a character. deletes held objects. removes anims from the HandStateObject
function freeHands(character)
local leftHeldObject = character.getLeftHeldObject();
if (leftHeldObject) then
character.detachLeftObjectHolder();
print("deleting leftHeldObject " .. leftHeldObject.getResourceName());
leftHeldObject.deleteGameObject();
end
local rightHeldObject = character.getRightHeldObject();
if (rightHeldObject) then
character.detachRightObjectHolder();
print("deleting rightHeldObject " .. rightHeldObject.getResourceName());
rightHeldObject.deleteGameObject();
end
local hso = character.handSO;
if (not hso) then
print("freeHands no hand state object found");
else
hso.stopAnimation();
end
end
-- returns true if an activity on an object can be done by the given character
function activityPossible(characterGO, activityName, standardGO, data, ignoreBroken)
-- check debug flags first
if (CharacterAI.checkFailing(CharacterAI.ALWAYS_FAIL)) then return false; end
if (CharacterAI.checkFailing(CharacterAI.NEVER_FAIL)) then return true; end
if (not type(characterGO) == "userdata") then
print("WARNING activityPossible: characterGO not valid !!!!");
return false;
end
-- check if character is ashamed
if (standardGO.isCharacter()) then
if (isCharacterAshamed(characterGO, standardGO)) then
return false, NO_RELATIONSHIPCONDITION;
end
end
local activity = characterGO.createActivity(activityName, standardGO);
local activityResult = activity.getActivityResult(ignoreBroken);
-- -- do not make it possible to sleep in bed during day time
-- if (standardGO.hasBehavior("bed") and activityName == "sleep") then
-- if (enumCompare(standardGO.getGameObjectServer().getDayTime(), DAY)) then
-- activityResult = UNKNOWN
-- end
-- end
-- print("activityPossible " .. activityName .. " activityResult " .. tostring(activityResult));
return enumCompare(activityResult, POSSIBLE), activityResult;
end
function getActivityLength(activity)
local scale = activity.getEffectivity();
if (scale < 0.1) then scale = 1.0 end
local length = activity.getLength();
--if (length < 1000) then length = 5000 end
length = length / scale;
local name = activity.getActivityName();
print("getActivityLength for " .. name .. " l:" .. length .. " s:" .. scale);
return length, scale;
--return 10000, 2.0;
end
-- shows the repair menu if this game object is broken
-- this: a game object
-- returns true if the menu is shown
function repairMenu()
if (this.isBroken()) then
this.clearPieMenu();
local button ;
button = this.addPieMenuButton(PM_REPAIR, REPAIR_COMMAND);
button.addDescription(ACTIVITY, REPAIR);
return true;
else
return false;
end
end
-- this: a game object
function abortIfBroken(character)
if (this.isBroken()) then
print("object broken");
instantAbort(character, EMOTICON_CANNOT, "emoThink")
return true;
else
return false;
end
end
function playShowerAnim(shower, suffix)
local name = shower.getResourceName();
print("name:" .. name .. " suffix:" .. suffix);
if (name == "showerDesign") then
shower.startAnimation("showerDesign" .. suffix);
elseif (name == "showerModern") then
shower.startAnimation("showerModern" .. suffix);
elseif (name == "showerOldschool") then
shower.startAnimation("showerOldschool" .. suffix);
end
end
function holdsObject(character, objectType)
--print("objectType:" .. objectType);
local rightObject = character.getRightHeldObject();
local leftObject = character.getLeftHeldObject();
if (rightObject) then
--print("rightObjectType:" .. rightObject.getType());
if (rightObject.getType() == objectType) then
--print("RIGHT_HAND:" .. objectType);
return true, RIGHT_HAND;
end
end
if (leftObject) then
--print("leftObjectType:" .. leftObject.getType());
if (leftObject.getType() == objectType) then
--print("LEFT_HAND:" .. objectType);
return true, LEFT_HAND;
end
end
--print("NO_HAND:" .. objectType);
return false, nil;
end
function genderizeReal(character, name)
local male = (character.isMale() and not character.isTransgender()) or
(not character.isMale() and character.isTransgender());
return name .. cond(male, "Mike", "Elaine");
end
function genderizePink(character, name)
local male = character.isMale()
local homo = character.isTransgender()
local suffix = cond(character.isMale(), cond(homo, "Pacifica", "Mike"), cond(homo, "Tom", "Elaine"));
return name .. suffix;
end
function genderize(character, name)
if (character.isMale()) then
return name .. "Mike";
else
return name .. "Elaine";
end
end
function genderizeSpeech(character, name, active, activeDiff)
local maleIsActive = (character.isMale() == active);
local suffix1 = cond(activeDiff, cond(maleIsActive, "Mike", "Elaine"), "");
local homo = character.isTransgender();
local suffix2 = cond(character.isMale(), cond(homo, "Pacifica", "Mike"), cond(homo, "Tom", "Elaine"));
local result = name .. suffix1 .. "_" .. suffix2;
print("genderizeSpeech:" .. character.getCharacterName() .. " text:" .. name .. " active:" .. tostring(active));
print(">>>maleIsActive:" .. tostring(maleIsActive) .. " homo:" .. tostring(homo));
print(">>>return: " .. result);
return result;
end
function archize(character, name)
return name .. getArchtypeSuffix(character);
end
function archizeRun(character, name)
local archtype = character.getArchtype();
local suffix = "Standard";
if (character.isMale()) then
if (enumCompare(archtype, CHIEF)) then suffix = "Standard";
elseif (enumCompare(archtype, BAD_BOY)) then suffix = "Bold";
elseif (enumCompare(archtype, BEST_FRIEND)) then suffix = "Standard";
elseif (enumCompare(archtype, CHARMER)) then suffix = "Standard";
elseif (enumCompare(archtype, LOST_SOUL)) then suffix = "Bold";
elseif (enumCompare(archtype, PROFESSOR)) then suffix = "Standard";
elseif (enumCompare(archtype, SWASHBUCKLER)) then suffix = "Bold";
elseif (enumCompare(archtype, WARRIOR)) then suffix = "Sexy";
else suffix = "-Standard"; end;
else
if (enumCompare(archtype, BOSS)) then suffix = "Sexy";
elseif (enumCompare(archtype, SEDUCTRESS)) then suffix = "Sexy";
elseif (enumCompare(archtype, SPUNKY_KID)) then suffix = "Sexy";
elseif (enumCompare(archtype, FREE_SPIRIT)) then suffix = "Aktivist";
elseif (enumCompare(archtype, INNOCENT_GIRL)) then suffix = "Sexy";
elseif (enumCompare(archtype, SCIENTIST)) then suffix = "Aktivist";
elseif (enumCompare(archtype, ACTIVIST)) then suffix = "Aktivist";
elseif (enumCompare(archtype, NURSE)) then suffix = "Sexy";
else suffix = "-Sexy"; end;
end
return name .. suffix;
end
function archizeWalk(character, name)
local archtype = character.getArchtype();
local male = character.isMale() and not character.isTransgender();
return name .. cond(male, "Mike", "Elaine");
end
function getArchtypeSuffix(character)
local archtype = character.getArchtype();
if (character.isMale()) then
if (enumCompare(archtype, CHIEF)) then return "Chief";
elseif (enumCompare(archtype, BAD_BOY)) then return "Badboy";
elseif (enumCompare(archtype, BEST_FRIEND)) then return "Bestfriend";
elseif (enumCompare(archtype, CHARMER)) then return "Charmer";
elseif (enumCompare(archtype, LOST_SOUL)) then return "Lostsoul";
elseif (enumCompare(archtype, PROFESSOR)) then return "Professor";
elseif (enumCompare(archtype, SWASHBUCKLER)) then return "Swashbuckler";
elseif (enumCompare(archtype, WARRIOR)) then return "Warrior";
else return "Mike"; end;
else
if (enumCompare(archtype, BOSS)) then return "Boss";
elseif (enumCompare(archtype, SEDUCTRESS)) then return "Seductress";
elseif (enumCompare(archtype, SPUNKY_KID)) then return "Spunkykid";
elseif (enumCompare(archtype, FREE_SPIRIT)) then return "Freespirit";
elseif (enumCompare(archtype, INNOCENT_GIRL)) then return "Innocentgirl";
elseif (enumCompare(archtype, SCIENTIST)) then return "Scientist";
elseif (enumCompare(archtype, ACTIVIST)) then return "Activist";
elseif (enumCompare(archtype, NURSE)) then return "Nurse";
else return "Elaine"; end;
end
end
function findBedForInteraction(character1, character2)
local beds = character1.getObjectsWithBehavior("doublebed");
for b = 1, getn(beds) do
local bed = beds[b];
if (not bed.isBroken()) then
local actionPoint1 = character1.getClosestFreeActionPoint(character1, bed, {"layDown1", "layDown2"});
if (actionPoint1 and character1.canReachActionPoint(actionPoint1)) then
local actionPoint2Name;
if (actionPoint1.getName() == "layDown1") then
actionPoint2Name = "layDown2";
else
actionPoint2Name = "layDown1";
end
local actionPoint2 = character2.getClosestFreeActionPoint(character2, bed, {actionPoint2Name});
if (actionPoint2 and character2.canReachActionPoint(actionPoint2)) then
return bed, actionPoint1, actionPoint2;
else
print("findBedForInteraction actionPoint2 not found or cannot reach");
end
else
print("findBedForInteraction actionPoint1 not found or cannot reach");
end
else
print("findBedForInteraction bed.isBroken");
end
end
return nil
end
function getInteractionBed(character1, character2)
local sm1 = character1.walkSO.getStateMachine().getName();
local s1 = character1.walkSO.getState();
local sm2 = character2.walkSO.getStateMachine().getName();
local s2 = character2.walkSO.getState();
--if ((sm1 ~= "doublebedChar") or (s1 ~= "doIntimate")) then
if (sm1 ~= "doublebedChar") then
-- print("getInteractionBed: wrong state char 1 :" .. sm1 .. "." .. s1);
return nil
end;
--if ((sm2 ~= "doublebedChar") or (s2 ~= "doIntimate")) then
if (sm2 ~= "doublebedChar") then
-- print("getInteractionBed: wrong state char 2 :" .. sm2 .. "." .. s2);
return nil
end;
local bed1 = character1.getObjectWithActivity("lie");
local bed2 = character2.getObjectWithActivity("lie");
if (not bed1) then
-- print("getInteractionBed: no bed1");
return nil;
end;
if (not bed2) then
-- print("getInteractionBed: no bed2");
return nil;
end;
if (bed1 ~= bed2) then
-- print("getInteractionBed: diferrent beds");
return nil;
end;
return bed1;
end
function getIntimateBed(character1, character2)
local interactionBed = getInteractionBed(character1, character2);
if (not interactionBed) then return nil end;
local s1 = character1.walkSO.getState();
local s2 = character2.walkSO.getState();
if (s1 ~= "doIntimate") then
print("getInteractionBed: wrong state char 1 :" .. s1);
return nil
end;
if (s2 ~= "doIntimate") then
print("getInteractionBed: wrong state char 2 :" .. s2);
return nil
end;
return interactionBed;
end
function getOtherUsers(character, object, activity)
local result = {};
local users = object.getCharactersWithActivity(activity);
for u = 1, getn(users) do
local user = users[u];
if (user ~= character) then
tinsert(result, user);
end
end
return result;
end
function getOtherUser(character, object, activity)
local otherUsers = getOtherUsers(character, object, activity);
return otherUsers[1];
end
function getCharactersWithActivities(object, activities)
local result = {};
for a = 1, getn(activities) do
local activity = activities[a];
local users = object.getCharactersWithActivity(activity);
for u = 1, getn(users) do
local user = users[u];
tinsert(result, user);
end
end
return result;
end
function isUser(character, object, activities)
for a = 1, getn(activities) do
local activity = activities[a];
local users = object.getCharactersWithActivity(activity);
for u = 1, getn(users) do
local user = users[u];
if (user == character) then
return true;
end
end
end
return nil;
end
function changeOutfit(character, outfit)
if (not hasOutfit(character, outfit)) then
character.changeOutfit(outfit);
else
print("already had that outfit");
end
end
function hasOutfit(character, outfit)
local current = character.getOutfit();
return (enumCompare(outfit, current));
end
function getChangeOutfitAnim(character)
if (hasOutfit(character, ARCHTYPE) or hasOutfit(character, STANDARD)) then
print("getChangeOutfitAnim ausziehen2");
return "ausziehen2";
else
print("getChangeOutfitAnim ausziehen1");
return "ausziehen1";
end;
end
function replaceActivities(object, oldActivities, newActivity)
local allUsers = {};
for a = 1, getn(oldActivities) do
local oldActivity = oldActivities[a];
local users = object.getCharactersWithActivity(oldActivity);
for u = 1, getn(users) do
local user = users[u];
user.stopActivity(oldActivity, object);
tinsert(allUsers, user);
end
end
if (not newActivity) then return end;
for u = 1, getn(allUsers) do
local user = allUsers[u];
user.startActivity(newActivity, object);
end
end
function getTableVersion(object)
if (not object) then return nil; end;
local name = object.getResourceName();
local tableName = "";
if (name == "pizzaBox") then tableName = "tabletPizza";
elseif (name == "boardgameBox") then tableName = "boardgame";
end;
if (tableName == "") then
return object;
else
local tableVer = getParent().loadGameObject("StandardGO", tableName);
return tableVer;
end
end
function getDirtyDishVersion(object)
local leftoverName = "plate";
if (not object) then
print("getDirtyDishVersion(nil) returning plate");
else
local name = object.getResourceName();
if (name == "tabletPizza") then leftoverName = "dirtyDishPizza";
elseif (name == "tabletBreakfast") then leftoverName = "dirtyDishBreakfast";
elseif (name == "tabletCooked") then leftoverName = "dirtyDishCooked";
elseif (name == "tabletDinner") then leftoverName = "dirtyDishDinner";
end;
end;
local dirtyDish = getParent().loadGameObject("StandardGO", leftoverName);
if (not dirtyDish) then
print("getDirtyDishVersion(" .. name .. ") = " .. leftoverName .. " NOT FOUND");
end;
return dirtyDish;
end
-- called by an objects msg handler to instantly abort an impossible action.
-- character must be in the walk-SM
function instantAbort(character, emoticon, emoMsg, sender)
print("instantAbort by " .. character.getCharacterName());
-- there could be a walk in the queue when walkToActionPoint
-- was called to find out that there is no path. clear it:
character.walkSO.clearQueue();
local stateMachine = character.walkSO.getStateMachine();
local stateMachineName = stateMachine.getName();
if (stateMachineName ~= "walk") then
print("instantAbort(".. character.getCharacterName() ..") is in state machine " .. stateMachineName);
-- remove the aborted queue entry manualy, because we cannot call nextAction()
character.popQueueEntry();
else
character.walkSO.nextAction();
end
if (not character.getLastMsgAI()) then
print("instantAbort user action");
if (emoticon) then character.setEmoticon(emoticon, EMOTICON_DELAY); end;
if (emoMsg) then
if (sender) then
sender.sendDelayedMsg(emoMsg, character.walkSO, 500);
else
sendDelayedMsg(emoMsg, character.walkSO, 500);
end;
end;
else
print("instantAbort AI action");
end
end
-- called by an objects msg handler to instantly abort an impossible action.
-- character must be in the walk-SM
function instantAbortIfNotIdle(character, charcterToCheck)
if (not isIdle(charcterToCheck) or charcterToCheck.isSwimming()) then
instantAbort(character, EMOTICON_CANNOT, "emoThink");
return true;
else
return false;
end;
end
-- called by an objects msg handler to instantly abort an impossible action.
-- character must be in the walk-SM
function instantAbortIfUnhappy(character, activityName, object)
local alwaysFail = (CharacterAI.checkFailing(CharacterAI.ALWAYS_FAIL));
local neverFail = (CharacterAI.checkFailing(CharacterAI.NEVER_FAIL));
local activity = character.createActivity(activityName, object);
local minSatisfaction = activity.getRequiredSatisfaction();
local satisfaction = character.calculateSatisfaction();
print("instantAbortIfUnhappy minSatisfaction " .. minSatisfaction .. " satisfaction:" .. satisfaction);
if ((satisfaction < minSatisfaction or alwaysFail) and (not neverFail)) then
instantAbort(character, EMOTICON_SAD, "emoRefuseChar", object);
return true;
else
return false;
end;
end
-- this: game object
function sendMsgAllUsers(msg, activities, data)
local users = getCharactersWithActivities(this, activities);
for u = 1, getn(users) do
local user = users[u];
if (data) then
sendMsg(msg, user.walkSO, data);
else
sendMsg(msg, user.walkSO);
end
end
end
-- this: tv or pc object in a active state
function startAnim(frames, frameDurration)
if (not frameDurration) then frameDurration = TV_ANIM_FRAME_DURRATION; end;
for f = 1, getn(frames) do
local frame = frames[f];
--print(frame);
sendDelayedMsgThis("showPic", (f-1) * frameDurration, frame);
end
sendDelayedMsgThis("startAnim", getn(frames) * frameDurration);
end
function preloadTextures(object, texures)
for t = 1, getn(texures) do
object.preloadTexture(texures[t]);
end
end
-- this: walkSO
function createDirt(dirtType, size, probability)
if (not probability) then probability = 1.0; end; -- default value
local character = getParent();
local messy = character.getCharacterCondition(CHAR_MESSY);
messy = 0.1 * messy; -- convert to 0.0 .. 1.0
--print("prob " .. probability * messy)
probability = probability * messy;
if (random() > probability) then
--print("createDirt probability: " .. probability .. " messy: " .. messy);
return
end;
-- dont make dirt on some floor types
local floorGO = getParent().getFloorUnderCharacter();
if (floorGO) then
local foorType = floorGO.getFloorType();
if (tfind(NO_DIRT_FLOOR_TYPES, foorType)) then
--print("createDirt foorType " .. foorType);
return
end;
end;
-- don't make dirt outside
local roomNumber = character.getRoomNumber();
local room = character.getGameObjectServer().getApartment().getRoom(roomNumber);
if (not room.isIndoor()) then
--print("createDirt outside");
return
end;
-- dont make dirt if cleaning
local holds, hand = holdsObject(character, "hoover");
if (holds) then return end;
-- dont make dirt if someonelse cleaning
local others = getCharactersHoldingObject(character, "hoover")
if (getn(others) > 0) then return end;
--print("createDirt by " .. character.getCharacterName());
character.createDirt(size, dirtType);
end
function getCharactersHoldingObject(character, objectType)
local result = {};
local others = character.getOtherCharacters();
for c = 1, getn(others) do
if (holdsObject(others[c], objectType)) then
tinsert(result, others[c]);
end;
end
return result;
end
-- this: walkSO
function createTrash(amount)
-- dont make dirt if cleaning
local character = getParent();
-- remaining trash to distribute
local remain = amount;
local trashCans = character.getObjectsWithBehavior("trashCan");
-- go trough trashCans
for t = 1, getn(trashCans) do
print(" createTrash trashCan:" .. t .. " remain:" .. remain);
local trashCan = trashCans[t];
remain = addTrash(trashCan, remain);
if (remain < 0.01) then
return
end;
end
-- TODO: place remaing trash on floor near character
character.createDirt(max(TRASH_TO_DIRT*remain, 0.1), DIRT_TRASH);
end
function addTrash(trashCan, amount)
local canType = trashCan.getType();
local capacity = trashCan.capacity;
--if (canType == "TrashCanModern") then capacity = 1.5 end;
local fillLevel = trashCan.retrieveData("fillLevel", 0.0);
local newFillLevel = fillLevel + (amount/capacity);
local remain = max(0.0, newFillLevel - 1.0);
newFillLevel = clamp(newFillLevel, 0.0, 1.0);
print("addTrash cap:" .. capacity .. " old:" .. fillLevel .. " delta:" .. amount .. " new:" .. newFillLevel.. " remain:" .. remain);
trashCan.storeData("fillLevel", newFillLevel);
local stinkRate = newFillLevel;
if (stinkRate < MIN_STINK_RATE) then
print("no emit")
trashCan.setChildEnable("stink", false);
else
print("emit")
trashCan.setChildEnable("stink", true);
stink = trashCan.findChildGO("stink");
stink.setEmitRate(stinkRate);
end
trashCan.setDirtiness(newFillLevel/FULL_TRASHCAN_DIRTINESS);
return remain;
end
function getDish(sink)
local dishes = getChildrenWithBehavior(sink, "dish");
return getn(dishes);
end
function addDish(sink, amount)
local dishes = getChildrenWithBehavior(sink, "dish");
local numDishes = getn(dishes);
local maxDishes = sink.maxDishes;
print("addDish(" .. amount .. ") current:" .. numDishes);
if (amount > 0) then
local toAdd = min(amount, maxDishes-numDishes);
print("addDish toAdd:" .. toAdd);
for i = 1, toAdd do
local dish = sink.loadGameObject("StandardGO", "plate");
local offsetZ = sink.dishesBaseHeight + (numDishes * dish.stackingZAdd);
sink.addObjectToActionPoint(dish, "dish", 0, 0, offsetZ);
numDishes = numDishes + 1;
end
return numDishes;
elseif (amount < 0) then
local toSub = min(abs(amount), numDishes);
print("addDish toSub:" .. toSub);
for i = 1, toSub do
local dish = dishes[(numDishes-i+1)];
dish.deleteGameObject();
end
return numDishes-toSub;
end
return numDishes;
end
function activeDiff(interaction)
if (interaction == "talkFlirt") then return false; end;
if (interaction == "talkGossip") then return false; end;
return true;
end
function isMonologue(interaction)
if (interaction == "talkRelation") then return true; end;
return false;
end
function getIconForAction(action)
if (action == "talkHobby") then return EMOTICON_HOBBY end;
if (action == "talkComfort") then return EMOTICON_COMFORT end;
if (action == "talkCompliment") then return EMOTICON_COMPLIMENT end;
if (action == "talkRelation") then return EMOTICON_INLOVE end;
if (action == "talkArgue") then return EMOTICON_ARGUE end;
if (action == "talkCasual") then return EMOTICON_SMALLTALK end;
if (action == "talkJoke") then return EMOTICON_JOKE end;
if (action == "talkILoveYou") then return EMOTICON_INLOVE end;
if (action == "talkFlirt") then return EMOTICON_EROTIC end;
if (action == "talkTease") then return EMOTICON_TEASE end;
if (action == "talkGossip") then return EMOTICON_GOSSIP end;
return EMOTICON_DUNNO;
end
function isIdle(character)
local stateMachine = character.walkSO.getStateMachine();
local stateMachineName = stateMachine.getName();
if (stateMachineName ~= "walk") then
print("isIdle(".. character.getCharacterName() ..") is state machine " .. stateMachineName);
return false;
end
local activityQueueCount = character.getActivityQueueCount();
if (activityQueueCount > 0) then
print("isIdle(".. character.getCharacterName() ..") has " .. activityQueueCount .. " action queued");
return false;
end
return true;
end
-- sets the top queue entry to the given text. if
function setTopQueueEntry(character, buttonText, clearCancel)
local activityQueueCount = character.getActivityQueueCount();
print("setTopQueueEntry " .. activityQueueCount);
if (activityQueueCount == 0) then
character.pushQueueEntry(buttonText);
else
local entry = character.replaceQueueEntry(0, buttonText, not clearCancel);
-- if (clearCancel) then
-- entry.clearCancel();
-- character.clearCancel();
-- character.updateActivityQueue();
-- end
end
end
function queueFollowCommand(character, buttonText, command, object, data)
if (not character) then
print("queueFollowComand no character");
return
end
if (not object) then
print("queueFollowComand no object");
return
end
local activityQueueCount = character.getActivityQueueCount();
print("queueFollowComand " .. activityQueueCount);
if (activityQueueCount == 1) then
character.queueCommand(buttonText, command, object, data);
end
end
function isBarefoot(character)
local current = character.getOutfit();
return (enumCompare(TOWEL, current) or
enumCompare(SWIMMING, current) or
enumCompare(UNDERWEAR, current) or
enumCompare(NOTHING, current));
end
-- this: walkWSO
function makeStepSound(foorType)
if (not foorType) then
local floorGO = getParent().getFloorUnderCharacter();
if (floorGO) then
foorType = floorGO.getFloorType();
--print("makeStepSound type under character " .. foorType)
else
foorType = "";
--print("makeStepSound: no floor under character ")
end
end;
if isBarefoot(getParent()) then
foorType = "Barefoot";
end;
if (not tfind(STEP_SOUNDS, foorType)) then
foorType = "";
end;
local stepSound = "step" .. foorType;
stepSound = stepSound .. random(1,2);
--print("makeStepSound " .. stepSound);
getParent().playSound(stepSound);
end
-- this: walkWSO
function makeChairSound(chair, sound)
-- defaults
local chairType = chair.chairType;
if (not chairType) then chairType = "Wood"; end;
if (not sound) then sound = "Down"; end;
local character = getParent();
local name = "chair" .. sound .. chairType;
print("makeChairSound: " .. name);
chair.playSound(name);
end
-- this: walkWSO
function groan(n)
--if (getParent().isMale() == true) then
if (false) then
return
else
if (not n) then n = random(1,9); end;
local sound = "groan" .. n;
sound = genderizeReal(getParent(), sound);
print("sound " .. sound .. " by " .. getParent().getCharacterName());
getParent().playSound(sound);
end
end
function swapDirtTextures(object)
-- local textures = {"kloOldschool", "kloModern"}; -- TODO: get from dynamic attribs
if (not object.dirtableTextures) or (not object.dirtSteps) then return end;
local textures = object.dirtableTextures;
local step = 1 / object.dirtSteps;
local dirt = object.getDirtiness();
local suffix = "";
local level = floor(dirt / step);
level = clamp(level, 0, object.dirtSteps - 1);
if (level > 0) then suffix = "_d" .. level; end;
print("dirtStep:" .. step .. " level:" .. level .. " suffix:" .. suffix);
-- if (dirt > 0.75) then suffix = "_d3";
-- elseif (dirt > 0.50) then suffix = "_d2";
-- elseif (dirt > 0.25) then suffix = "_d1";
-- end;
for i = 1, getn(textures) do
local texture = textures[i];
local newTexture = texture .. suffix;
print("swapDirtTextures: " .. texture .. " -> " .. newTexture);
object.replaceTexture(texture, newTexture);
end
end
function changeDirtiness(object, amount)
local oldDirt = object.getDirtiness();
local newDirt = oldDirt + amount;
newDirt = clamp(newDirt, 0.0, 1.0);
print("change dirt of " .. object.getType() .. " from " .. oldDirt .. " to " .. newDirt);
object.setDirtiness(newDirt);
swapDirtTextures(object);
end
-- this: walkWSO
function clean(object, amount)
local character = getParent();
local clean = character.createActivity("clean", object);
local effect = clean.getEffectivity();
amount = -(amount * effect);
changeDirtiness(object, amount);
end
-- this: walkWSO
function dirtify(object, amount)
local character = getParent();
local messy = character.getCharacterCondition(CHAR_MESSY);
messy = (0.1 * messy) - 0.5; -- scale to -1.0 .. 1.0
amount = max(amount, 0.0);
amount = amount + (amount * messy);
changeDirtiness(object, amount);
end
-- returns true (the name of the action point) if this door is a bathroom door
function isBathroomDoor(doorGO)
local actionPoints = doorGO.getActionPoints();
for i = 1, getn(actionPoints) do
local actionPoint = actionPoints[i];
local room = doorGO.getRoomFromActionPoint(actionPoint);
if (room) then
if (room.getRoomTypeValue(BATHROOM) > 0) then
return actionPoint.getName();
end
end
end
return false;
end
-- this: walkSO
function checkShortcut(object, commands, states, messages)
local character = getParent();
local entry = character.peekActivityQueue();
local entryCommand = entry.getCommand();
local entryObject = entry.getGameObject();
local entryData = entry.getData();
if (not object) then
print("checkShortcut no valid object");
return false;
end;
if (not entryObject) then
print("checkShortcut no valid entryObject:" .. tostring(entryObject));
return false;
end;
if (entryObject ~= object) then
print("checkShortcut wrong object:" .. object.getType() .. " queue:" .. entryObject.getType());
return false;
end
local index = tfind(commands, entryCommand)
if (not index) then index = tfind(commands, entryData) end;
if (not index) then
print("checkShortcut command not found! command:" .. entryCommand .. " data:" .. entryData);
return false
end
if (getn(commands) ~= getn(states)) then
print("checkShortcut given: " .. getn(commands) .. " commands but " .. getn(states) .. " states");
return false
end
print("checkShortcut -> taking shortcut to state: " .. states[index]);
character.popQueueEntry();
clearCancel();
if (messages) then
local message = messages[index];
if (message) then
print("checkShortcut sending msg:" .. message .. " data:" .. tostring(entryData) .. " to " .. object.getType());
character.sendMsg(message, entryObject, tostring(entryData));
end;
end
-- if (messages) then
-- local message = messages[index];
-- if (message) then
-- print("checkShortcut sending msg:" .. message .. " to " .. object.getType());
-- character.sendMsg(message, object);
-- end;
-- end
setState(states[index]);
-- if (messages) then
-- local message = messages[index];
-- if (message) then
-- local name, data = strsplit(message, ".");
-- if (data) then
-- print("checkShortcut sending msg:" .. name .. " data:" .. data .. " to " .. object.getType());
-- character.sendMsg(name, object, data);
-- else
-- print("checkShortcut sending msg:" .. name .. " to " .. object.getType());
-- character.sendMsg(name, object);
-- end
-- end;
-- end
return true;
end
-- this: walkSO
function checkWatchShortcut(object, commands, states, messages)
local character = getParent();
local entry = character.peekActivityQueue();
local entryCommand = entry.getCommand();
local entryObject = entry.getGameObject();
local entryData = entry.getData();
if (not object) then
print("checkShortcut no valid object");
return false;
end;
if (not entryObject) then
print("checkShortcut no valid entry");
return false;
end;
local optimalSeat = getNextWatchSit(character, entryObject, 1.0, 1.5);
if (not optimalSeat) then
print("checkShortcut no optimalSeat");
return false;
end
if (optimalSeat ~= object) then
print("checkShortcut wrong optimalSeat:" .. optimalSeat.getType() .. " currentSeat:" .. object.getType());
return false;
end
local index = tfind(commands, entryCommand)
-- if (not index) then index = tfind(commands, entryData) end;
if (not index) then
print("checkShortcut command not found! command:" .. entryCommand .. " data:" .. entryData);
return false
end
if (getn(commands) ~= getn(states)) then
print("checkShortcut given: " .. getn(commands) .. " commands but " .. getn(states) .. " states");
return false
end
print("checkShortcut -> taking shortcut to state: " .. states[index]);
character.popQueueEntry();
clearCancel();
if (messages) then
local message = messages[index];
if (message) then
print("checkShortcut sending msg:" .. message .. " data:" .. tostring(entryData) .. " to " .. object.getType());
character.sendMsg(message, entryObject, tostring(entryData));
end;
end
setState(states[index]);
return true;
end
function getSofaIteractionInfo(character1, character2)
local male = 0;
if (character1.isMale()) then male = 1; else male = 2; end;
local wso1 = character1.walkSO;
local wso2 = character2.walkSO;
local actionPointName1 = wso1.retrieveData("actionPointName");
local actionPointName2 = wso2.retrieveData("actionPointName");
if ((not actionPointName1) or (not actionPointName2)) then
print("getSofaIteractionInfo fail actionPointName");
return false;
end;
local sofa1 = character1.getObjectWithActivity("sit");
local sofa2 = character1.getObjectWithActivity("sit");
if ((not sofa1) or (not sofa2) or (sofa1 ~= sofa2)) then
print("getSofaIteractionInfo fail sofa");
return false;
end;
local possible;
local mirrorAnims;
if (actionPointName1 == "sit1" and actionPointName2 == "sit2") then
possible = true;
mirrorAnims = (male == 2);
elseif (actionPointName1 == "sit2" and actionPointName2 == "sit1") then
possible = true;
mirrorAnims = (male == 1);
elseif (actionPointName1 == "sit2" and actionPointName2 == "sit3") then
possible = true;
mirrorAnims = (male == 2);
elseif (actionPointName1 == "sit3" and actionPointName2 == "sit2") then
possible = true;
mirrorAnims = (male == 1);
else
possible = false;
mirrorAnims = false;
end
return possible, mirrorAnims;
end
-- this walkSO with "activePart" stored
function getInteractionWaitTime()
if retrieveData("activePart") or retrieveData("waitLong") then
return WAIT_INTERACTION_ACTIVE;
else
return WAIT_INTERACTION_PASSIVE;
end
end
function getStoredOrSender(name, msg)
if (type(name) == "table") then
for n = 1, getn(name) do
print(">getStoredOrSender name table element " .. name[n]);
local stored = retrieveStateObject(name[n]);
if (stored) then
print(">getStoredOrSender stored as " .. name[n]);
return stored;
end
end
else
local stored = retrieveStateObject(name);
if (stored) then
print(">getStoredOrSender stored as " .. name);
return stored;
end
end
print(">getStoredOrSender not stored");
return getStateObjectFromID(msg.sender);
end
function unlockAll(storeName)
local character = getParent();
local object = retrieveStateObject(storeName);
if (object) then
character.unlockActionPoints(object);
character.stopAllActivities(object);
object.stopAllSounds();
end;
removeStateObject(storeName);
end
function getEatActivityName(tablet)
local activity = tablet.activity;
if (not activity) then
activity = "eat";
end
return activity;
end
function hasLightenCandles(table)
local children = table.getGOChildren();
for c = 1, getn(children) do
local child = children[c];
if (child.hasBehavior("candle") and child.getLightOn()) then
return true;
end
end
return false;
end
-- this: walkSO
-- finds character sitting at the same table in front of this character
function getTableTalkPartner(tablet)
local table = retrieveStateObject("table");
local tableActionPointName = retrieveData("tableActionPointName");
if ((not table) or (not tableActionPointName)) then
print("lookForPartner: no table or tableActionPointName");
return nil;
end
local partnerChair = getOpposedChair(table, tableActionPointName);
if (not partnerChair) then
print("lookForPartner: no partner chair found");
return nil;
end
local siting = partnerChair.getCharactersWithActivity("sit");
local partner = siting[1];
if (not partner) then
print("lookForPartner: no partner found");
return nil;
end
-- somebody is sitting in front of characer -> smalltalk
print("partner found -> smalltalk");
return partner;
end
function canLeave(character)
local gameObjectServer = character.getGameObjectServer();
local current = gameObjectServer.getOutsideWorld();
local other = getOtherCharacter(character);
if ((not other) or (not other.getAtHome())) then
return false;
end;
if (enumCompare(current, CITY)) then
print("canLeave to COUNTRY");
local cheat = (readConfig("Debug", "beachHouseAlways", "false") == "true");
local neverFail = CharacterAI.checkFailing(CharacterAI.NEVER_FAIL);
if (cheat or neverFail) then
return true;
end
-- wenn sie das Ja-Wort gegeben hat - vorsicht nicht den honeymoonquest zerschiessen!!
if ( gameObjectServer["mission"] and
gameObjectServer["mission"]["questHoneymoon"] and
gameObjectServer["mission"]["questHoneymoon"].getState() == "done" ) then
return true;
-- -- TODO: check if they have the beach house already
-- local mike = gameObjectServer.getCharacter(MIKE);
-- local elaine = gameObjectServer.getCharacter(ELAINE);
-- local minCond = min( mike.getRelationshipCondition(ELAINE, REL_FRIENDSHIP),
-- elaine.getRelationshipCondition(MIKE, REL_FRIENDSHIP));
-- if (minCond < 5) then
-- return false;
-- end
------------------------------------------------------
-- local gameDate = gameObjectServer.getGameDate();
-- local weekDay = gameDate.getWeekDay();
-- local hour = gameDate.getHours();
--
-- if (enumCompare(weekDay, SATURDAY) or enumCompare(weekDay, SUNDAY)) then
-- return true;
-- end
--
-- if (enumCompare(weekDay, FRIDAY) and not character.timeForWork()) then
-- return true;
-- end
else
print("questHoneymoon not done yet ");
end
else
print("canLeave to CITY");
return true;
end
return false;
end
function toggleOutsideWorld(gameObject)
local gameObjectServer = gameObject.getGameObjectServer();
local current = gameObjectServer.getOutsideWorld();
if (enumCompare(current, CITY)) then
print("toggleOutsideWorld to COUNTRY");
gameObjectServer.setOutsideWorldDeferred(COUNTRY);
else
print("toggleOutsideWorld to CITY");
gameObjectServer.setOutsideWorldDeferred(CITY);
end
end
function getOtherWaitingToLeave(character, staircase)
local other = getOtherCharacter(character);
if (not other) or (not staircase) then return nil; end;
local oStateMachine = other.walkSO.getStateMachine().getName();
local oState = other.walkSO.getState();
local oStaircase = other.walkSO.retrieveStateObject("staircase");
-- print("getOtherWaitingToLeave oStateMachine " .. oStateMachine);
-- print("getOtherWaitingToLeave oState " .. oState);
-- print("getOtherWaitingToLeave oStaircase " .. tostring(oStaircase));
-- print("getOtherWaitingToLeave tStaircase " .. tostring(staircase));
-- if (oStaircase) then
-- print("getOtherWaitingToLeave oStaircase " .. oStaircase.getUniqueID());
-- end
-- print("getOtherWaitingToLeave tStaircase " .. staircase.getUniqueID());
if (oStateMachine == "staircaseChar") and (oState == "atOtherHouse") and (oStaircase == staircase) then
print("getOtherWaitingToLeave found");
return other;
end
return nil;
end
function getLeaveButtonText(gameObject)
local gameObjectServer = gameObject.getGameObjectServer();
local current = gameObjectServer.getOutsideWorld();
if (enumCompare(current, CITY)) then
return "pm_gotoCountry";
else
return "pm_gotoCity";
end
return "pm_goOut";
end
function getComeBackButtonText(gameObject)
local gameObjectServer = gameObject.getGameObjectServer();
local current = gameObjectServer.getOutsideWorld();
if (enumCompare(current, CITY)) then
return "pm_fromCountry";
else
return "pm_fromCity";
end
return "pm_goOut";
end
function canMarry(char1, char2)
if char1.isMale() then
local mike = char1;
local elaine = char2;
local friendship = min(mike.getRelationshipCondition(ELAINE, REL_FRIENDSHIP),
elaine.getRelationshipCondition(MIKE, REL_FRIENDSHIP));
local romantic = min(mike.getRelationshipCondition(ELAINE, REL_ROMANTIC),
elaine.getRelationshipCondition(MIKE, REL_ROMANTIC));
local erotic = min(mike.getRelationshipCondition(ELAINE, REL_EROTIC),
elaine.getRelationshipCondition(MIKE, REL_EROTIC));
local questHoneymoon = char1.getGameObjectServer()["mission"]["questHoneymoon"];
if (
not (questHoneymoon and questHoneymoon.getState() == "done")
and
(
( -- eines davon 10 und die anderen mindestens 5 sind und der honeymoon-quest schon im state "marryme" ist
max(max(friendship, romantic), erotic) >= 10
and
min(min(friendship, romantic), erotic) >= 5
and
questHoneymoon and questHoneymoon.getState() == "waitForMarriage"
)
or
( -- falls questHoneymoon hΣngt: alle drei Bewertungen 10 sind - man also praktisch fertig ist
min(min(friendship, romantic), erotic) >= 10
)
)
)
then
-- here condition for marriage
return true;
end
else
return false;
end
end
-- this: walkSO in intraction
function storeActivityPossible(activity)
local thisChar = getParent();
local partner = retrieveStateObject("partner");
if not partner then
print("storeActivityPossible no partner");
return
end
local partnerChar = partner.getParent();
local activePart = retrieveData("activePart");
local active = cond(activePart, thisChar, partnerChar);
local passive = cond(activePart, partnerChar, thisChar);
local result = activityPossible(active, activity, passive);
storeData("activityPossible", result);
print("storeActivityPossible stored: " .. tostring(result));
print(">>active : " .. active.getCharacterName());
print(">>passive : " .. passive.getCharacterName());
end
-- this: questSO
function talkingCancelled(charID, topic)
local gameObjectServer = getParent().getParent();
local character = gameObjectServer.getCharacter(charID);
if character then
local walkSO = character.walkSO;
if walkSO then
print("talkingCancelled topic: " .. topic .. " to" .. character.getCharacterName());
sendMsg("talkingCancelled", walkSO, topic);
end
end
end